package gui.admin;

import gui.AbstractDefensiveDriverPanel;
import gui.InvalidSyncPanelImpl;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import objects.DistanceLog;
import objects.GeneralLog;
import objects.SpeedLogReport;
import objects.StopSignLog;
import objects.Student;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import com.swtdesigner.SWTResourceManager;

public class AdminDriverProfilePanelImpl extends AbstractAdminPanelImpl implements AdminDriverProfilePanel {
	private Table speedLimitTable;
	private Table followingTable;
	private Table stopSignTable;
	private Table seatbeltTable;
	private TabFolder alerts;
	private Label mailingAddressLbl;
	private Label driverNameLbl;
	private Label phoneNumberLbl;
	private Label emailAddressLbl;
	private Label driverName;
	private Label phoneNumber;
	private Label emailAddress;
	private Label mailingAddress;
	private Button btnCollectAlerts;
	private Button btnDriverAnalysis;
	private TabItem speedAlertsTab;
	private TabItem followingAlertsTab;
	private TabItem stopSignAlertsTab;
	private TabItem seatBeltAlertsTab;
	private TableColumn speedDateCol;
	private TableColumn speedDurCol;
	private TableColumn speeCurCol;
	private TableColumn speedMaxCol;
	private TableColumn followDate;
	private TableColumn followDurCol;
	private TableColumn stopDateCol;
	private TableColumn seatbeltDateCol;
	private TableColumn seatbeltDurCol;
	
	private Student student;
	private ArrayList<SpeedLogReport> speedRecords = new ArrayList<SpeedLogReport>();
	private ArrayList<DistanceLog> distanceRecords = new ArrayList<DistanceLog>();
	private ArrayList<StopSignLog> stopSignRecords = new ArrayList<StopSignLog>();
	private ArrayList<GeneralLog> seatbeltRecords = new ArrayList<GeneralLog>();
	private Label tallyLbl;
	private Label tally;
	private ProgressPanelImpl progress;
	private AbstractDefensiveDriverPanel parent = this;
	private List<SpeedLogReport> speedStore = new ArrayList<SpeedLogReport>();
	private List<DistanceLog> distanceStore = new ArrayList<DistanceLog>();
	private List<StopSignLog> stopSignStore = new ArrayList<StopSignLog>();
	private List<GeneralLog> seatbeltStore = new ArrayList<GeneralLog>();
	
	public AdminDriverProfilePanelImpl(Display display, Shell shell) {
		super(display, shell);
		
		progress = new ProgressPanelImpl(display, new Shell());
		progress.setMessage("Updating Alerts");
		progress.setCaller(this);
	}

	/**
	 * @wbp.parser.entryPoint
	 */
	public void open() {
		// Remove at compile time
//		Shell shell = new Shell();
		// **********************
		
		shell.setSize(800, 600);
		shell.setText("Driver Profile");
		
		alerts = new TabFolder(shell, SWT.NONE);
		alerts.setBounds(10, 137, 764, 361);
		alerts.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(Event event) {
				setTally();
			}
		});
		
		speedAlertsTab = new TabItem(alerts, SWT.NONE);
		speedAlertsTab.setText("Speed Limit Alerts");
		
		speedLimitTable = new Table(alerts, SWT.BORDER | SWT.FULL_SELECTION);
		speedLimitTable.setLinesVisible(true);
		speedLimitTable.setHeaderVisible(true);
		speedAlertsTab.setControl(speedLimitTable);
		
		speedDateCol = new TableColumn(speedLimitTable, SWT.NONE);
		speedDateCol.setWidth(100);
		speedDateCol.setText("Date");
		
		speedDurCol = new TableColumn(speedLimitTable, SWT.NONE);
		speedDurCol.setWidth(196);
		speedDurCol.setText("Duration (sec)");
		
		speeCurCol = new TableColumn(speedLimitTable, SWT.NONE);
		speeCurCol.setWidth(210);
		speeCurCol.setText("Recorded Speed");
		
		speedMaxCol = new TableColumn(speedLimitTable, SWT.NONE);
		speedMaxCol.setWidth(235);
		speedMaxCol.setText("Speed Limit");
		
		followingAlertsTab = new TabItem(alerts, SWT.NONE);
		followingAlertsTab.setText("Following Too Closely Alerts");
		
		followingTable = new Table(alerts, SWT.BORDER | SWT.FULL_SELECTION);
		followingAlertsTab.setControl(followingTable);
		followingTable.setHeaderVisible(true);
		followingTable.setLinesVisible(true);
		
		followDate = new TableColumn(followingTable, SWT.NONE);
		followDate.setWidth(200);
		followDate.setText("Date");
		
		followDurCol = new TableColumn(followingTable, SWT.NONE);
		followDurCol.setWidth(232);
		followDurCol.setText("Duration (sec)");
		
		stopSignAlertsTab = new TabItem(alerts, SWT.NONE);
		stopSignAlertsTab.setText("Stop Sign Alerts");
		
		stopSignTable = new Table(alerts, SWT.BORDER | SWT.FULL_SELECTION);
		stopSignAlertsTab.setControl(stopSignTable);
		stopSignTable.setHeaderVisible(true);
		stopSignTable.setLinesVisible(true);
		
		stopDateCol = new TableColumn(stopSignTable, SWT.NONE);
		stopDateCol.setWidth(119);
		stopDateCol.setText("Date");
		
		seatBeltAlertsTab = new TabItem(alerts, SWT.NONE);
		seatBeltAlertsTab.setText("Seatbelt Alerts");
		
		seatbeltTable = new Table(alerts, SWT.BORDER | SWT.FULL_SELECTION);
		seatBeltAlertsTab.setControl(seatbeltTable);
		seatbeltTable.setHeaderVisible(true);
		seatbeltTable.setLinesVisible(true);
		
		seatbeltDateCol = new TableColumn(seatbeltTable, SWT.NONE);
		seatbeltDateCol.setWidth(100);
		seatbeltDateCol.setText("Date");
		
		seatbeltDurCol = new TableColumn(seatbeltTable, SWT.NONE);
		seatbeltDurCol.setWidth(229);
		seatbeltDurCol.setText("Duration (sec)");
		
		driverNameLbl = new Label(shell, SWT.NONE);
		driverNameLbl.setBounds(10, 47, 123, 24);
		driverNameLbl.setText("Driver Name:");
		driverNameLbl.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		mailingAddressLbl = new Label(shell, SWT.NONE);
		mailingAddressLbl.setBounds(350, 47, 153, 24);
		mailingAddressLbl.setText("Mailing Address:");
		mailingAddressLbl.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		phoneNumberLbl = new Label(shell, SWT.NONE);
		phoneNumberLbl.setBounds(10, 77, 143, 24);
		phoneNumberLbl.setText("Phone Number:");
		phoneNumberLbl.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		emailAddressLbl = new Label(shell, SWT.NONE);
		emailAddressLbl.setBounds(10, 107, 143, 24);
		emailAddressLbl.setText("Email Address:");
		emailAddressLbl.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		driverName = new Label(shell, SWT.NONE);
		driverName.setForeground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_DARK_SHADOW));
		driverName.setBounds(139, 47, 205, 24);
		driverName.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		phoneNumber = new Label(shell, SWT.NONE);
		phoneNumber.setForeground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_DARK_SHADOW));
		phoneNumber.setBounds(159, 77, 185, 24);
		phoneNumber.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		emailAddress = new Label(shell, SWT.NONE);
		emailAddress.setForeground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_DARK_SHADOW));
		emailAddress.setBounds(159, 107, 344, 24);
		emailAddress.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		mailingAddress = new Label(shell, SWT.NONE);
		mailingAddress.setForeground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_DARK_SHADOW));
		mailingAddress.setBounds(509, 47, 265, 54);
		mailingAddress.setFont(new Font(display, "Arial", 16, SWT.WRAP));
		
		btnDriverAnalysis = new Button(shell, SWT.NONE);
		btnDriverAnalysis.setBounds(685, 504, 89, 25);
		btnDriverAnalysis.setText("Driver Analysis");
		btnDriverAnalysis.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(Event event) {
				AdminDriverAnalysisPanel window = new AdminDriverAnalysisPanelImpl(display, shell);
				window.setStudent(student);
				dispose();
				window.open();
			}
		});
		
		btnCollectAlerts = new Button(shell, SWT.NONE);
		btnCollectAlerts.setBounds(590, 504, 89, 25);
		btnCollectAlerts.setText("Collect Alerts");
		btnCollectAlerts.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(Event event) {
				try {
					if(progress.isDisposed()) {
						progress = new ProgressPanelImpl(display, new Shell());
						progress.setCaller(parent);
						progress.setMessage("Updating Users");
					}
					progress.open();
					database.dsm();
				} catch (SQLException e) {
					InvalidSyncPanelImpl window = new InvalidSyncPanelImpl(display, new Shell());
					window.open();
					e.printStackTrace();
				}
				loadFollowingAlerts();
				loadSeatBeltAlerts();
				loadSpeedLimitAlerts();
				loadStopSignAlerts();
			}
		});
		
		tallyLbl = new Label(shell, SWT.NONE);
		tallyLbl.setBounds(10, 504, 47, 25);
		tallyLbl.setText("Total:");
		tallyLbl.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		tally = new Label(shell, SWT.NONE);
		tally.setBounds(63, 504, 70, 25);
		tally.setFont(new Font(display, "Arial", 16, SWT.NONE));
		
		// Set Labels
		setDriverName(student.getName());
		setPhoneNumber("(555) 555-5555");
		setEmailAddress(student.getName().toLowerCase() + "@cs.odu.edu");
		setMailingAddress(student.getAddress());
		
		loadSpeedLimitAlerts();
		loadFollowingAlerts();
		loadStopSignAlerts();
		loadStopSignAlerts();
		setTally();

		shell.open();
		shell.layout();
	}
	@Override
	public void setStudent(Student student) {
		this.student = student;
	}
	@Override
	public void setDriverName(String driverName) {
		this.driverName.setText(driverName);
		this.driverName.update();
	}
	@Override
	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber.setText(phoneNumber);
		this.phoneNumber.update();
	}
	@Override
	public void setEmailAddress(String emailAddress) {
		this.emailAddress.setText(removeSpaces(emailAddress));
		this.emailAddress.update();
	}
	@Override
	public void setMailingAddress(String mailingAddress) {
		this.mailingAddress.setText(mailingAddress);
		this.mailingAddress.update();
	}
	@Override
	public void setTally(String tally) {
		if(tally == null) {
			tally = "0";
		}
		this.tally.setText(tally);
		this.tally.update();
	}
	@Override
	public void setTally() {
		if(tally != null) {
			int selected = alerts.getSelectionIndex();
			switch(selected) {
				case 0:
					setTally(Integer.toString(speedStore.size()));
					break;
				case 1:
					setTally(Integer.toString(distanceStore.size()));
					break;
				case 2:
					setTally(Integer.toString(stopSignStore.size()));
					break;
				case 3:
					setTally(Integer.toString(seatbeltStore.size()));
					break;
				default:
					setTally("0");
					break;
			}
		}
	}
	@Override
	public void loadSpeedLimitAlerts() {
		try {
			database.getSpeedLogsbyStID(speedRecords, student.getID());
		} catch (SQLException e) {
			System.out.println("Unable to get reports");
			e.printStackTrace();
		}
		
		for(SpeedLogReport r : speedRecords) {
			if(!speedStoreContains(r)) {
				TableItem item = new TableItem(speedLimitTable, SWT.NONE);
				SimpleDateFormat fmt = new SimpleDateFormat("MMM d, yyyy");
				Date d = new Date(r.getTimeSt().getTime());
				String date = fmt.format(d);
				item.setText(new String[] {date, Integer.toString(r.getDuration()/1000),
						Integer.toString(r.getCurrSpeed()), Integer.toString(r.getSpeedLimit())});
				speedStore.add(r);
			}
		}
	}
	@Override
	public void loadFollowingAlerts() {
		try {
			database.getDistanceLogsbyStID(distanceRecords, student.getID());
		} catch (SQLException e) {
			System.out.println("Unable to get reports");
			e.printStackTrace();
		}
		
		for(DistanceLog r : distanceRecords) {
			if(!distanceStoreContains(r)) {
				TableItem item = new TableItem(followingTable, SWT.NONE);
				SimpleDateFormat fmt = new SimpleDateFormat("MMM d, yyyy");
				Date d = new Date(r.getTimeSt().getTime());
				String date = fmt.format(d);
				item.setText(new String[] {date, Integer.toString(r.getDuration()/1000)});
				distanceStore.add(r);
			}
		}
	}
	@Override
	public void loadStopSignAlerts() {
		try {
			database.getStopLogsbyStID(stopSignRecords , student.getID());
		} catch (SQLException e) {
			System.out.println("Unable to get reports");
			e.printStackTrace();
		}
		
		for(StopSignLog r : stopSignRecords) {
			if(!stopSignStoreContains(r)) {
				TableItem item = new TableItem(stopSignTable, SWT.NONE);
				SimpleDateFormat fmt = new SimpleDateFormat("MMM d, yyyy");
				Date d = new Date(r.getTimeSt().getTime());
				String date = fmt.format(d);
				item.setText(new String[] {date});
				stopSignStore.add(r);
			}
		}
	}
	@Override
	public void loadSeatBeltAlerts() {
		try {
			database.getGeneralLogsbyStID(seatbeltRecords , student.getID());
		} catch (SQLException e) {
			System.out.println("Unable to get reports");
			e.printStackTrace();
		}
		
		for(GeneralLog r : seatbeltRecords) {
			if(!seatbeltStoreContains(r)) {
				TableItem item = new TableItem(seatbeltTable, SWT.NONE);
				SimpleDateFormat fmt = new SimpleDateFormat("MMM d, yyyy");
				Date d = new Date(r.getTimeSt().getTime());
				String date = fmt.format(d);
				item.setText(new String[] {date, Integer.toString(r.getDuration()/1000)});
				seatbeltStore.add(r);
			}
		}
	}
	
	private boolean speedStoreContains(SpeedLogReport r) {
		for(SpeedLogReport s : speedStore) {
			if(s.getID() == r.getID()) {
				return true;
			}
		}
		return false;
	}
	
	private boolean distanceStoreContains(DistanceLog r) {
		for(DistanceLog d : distanceStore ) {
			if(d.getID() == r.getID()) {
				return true;
			}
		}
		return false;
	}

	private boolean stopSignStoreContains(StopSignLog r) {
		for(StopSignLog s : stopSignStore) {
			if(s.getID() == r.getID()) {
				return true;
			}
		}
		
		return false;
	}

	private boolean seatbeltStoreContains(GeneralLog r) {
		for(GeneralLog g : seatbeltStore) {
			if(g.getID() == r.getID()) {
				return true;
			}
		}
		return false;
	}
}
